package cs348a.opengl;

import javax.media.opengl.GL;
import javax.media.opengl.GLAutoDrawable;
import javax.media.opengl.glu.GLU;

/**
 * <code>OpenGLPerspective</code> is a class that
 * contains perspective related values and updates the GL.
 * An <code>OpenGLPerspective</code> can be thought of as a camera.
 * Translating or rotating the perspective is equivalent to
 * moving or turning the camera.
 */
public class JoglPerspective {		
	static public double DEFAULT_LENGTH = 512;
	static public double DEFAULT_ANGLE = 150;
	
	static public double MAX_ANGLE = 150.0;
	static public double MIN_ANGLE = 1.0;
	
	/** Enables the perspective view */
	private boolean enablePerspective = false;
	
	/** angle of view */
	public double angle = DEFAULT_ANGLE;
	
	/** near limit */
	public double near = 1;
	
	/** far limit */
	public double far = 1000;
	
	/** width of the orthographic perspective */
	public double orthoWidth = DEFAULT_LENGTH;
	
	/** height of the orthographic perspective */
	public double orthoHeight = DEFAULT_LENGTH;
	
	/** The position of the view */
	public float[] viewPosition = new float[]{0, 0, 0};
	
	/** The position of the object */
	public float[] objectPosition = new float[]{0, 0, -1};

	/** The "up" direction of the view */
	public float[] upDirection = new float[]{0, 1, 0};
	
	/**
	 * Enables the perspective view. 
	 * 
	 * @param enable
	 */
	public void setEnabled(boolean enable){
		enablePerspective = enable;
	}
	
	/**
	 * Returns true is perspective is enabled.
	 * 
	 * @return
	 */
	public boolean isEnabled(){
		return enablePerspective;
	}
	
	/**
	 * Updates the direction of the view(camera).
	 * 
	 * @param drawable
	 */
	public void updateView(GLAutoDrawable drawable) {
		GL gl = drawable.getGL();
		
		gl.glLoadIdentity();
		new GLU().gluLookAt(
				viewPosition[0], viewPosition[1], viewPosition[2], 
				objectPosition[0], objectPosition[1], objectPosition[2],
				upDirection[0], upDirection[1], upDirection[2]);
	}
	
	/**
	 * Updates the perspective. 
	 * 
	 * @param drawable
	 * @param ratio - width/height
	 */
	public void updatePerspective(GLAutoDrawable drawable, double ratio){
		GL gl = drawable.getGL();
		
		gl.glMatrixMode(GL.GL_PROJECTION);	// select the projection matrix
		gl.glLoadIdentity();				// reset the projection matrix

		if(enablePerspective) {
			GLU glu = new GLU();
			glu.gluPerspective(angle, ratio, near, far);
		} else {
			double width = orthoWidth;
			double height = orthoHeight;
			if(ratio > 1){
				width *= ratio;
			} else {
				height /= ratio;
			}
			gl.glOrtho(-width/2, width/2, -height/2, height/2, near, far);
		}
		
		gl.glMatrixMode(GL.GL_MODELVIEW);	// select the modelview matrix
		gl.glLoadIdentity();				// reset the modelview matrix
	}
}
